/*
 * Copyright (c) 2006-2021, Halo team
 *
 * SPDX-License-Identifier: GPLv3
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-11     Eywen        the first version
 */

#include "filament_runout.h"

/* 触发限位开关后的回调函数  */
static void filament_runout_level_changed_event(void *args)
{
    filament_runout_t *filament_runout;
    filament_runout = (filament_runout_t *)args;
    ASSERT_NULL(filament_runout);

    motion_step_t *motion_step;
    motion_step = filament_runout->motion_step_relevancy;
    ASSERT_NULL(motion_step);

    smart_step_t *smart_step;
    smart_step = filament_runout->motion_step_relevancy->step_drv;
    /* 触发了限位开关 */

    /* 复位脉冲计数值,便于计算当前步进电机的位置 */
    smart_step->ops->reset_cur_pulse_loc(smart_step);
}

/* 初始化限位开为关 */
bool filament_runout_init(filament_runout_t *device, int pin, bool level,
                  motion_step_t *step)
{
    ASSERT_NULL(device);
    ASSERT_NULL(step);

    /* 指定的引脚 */
    device->pin = pin;
    /* 绑定的步进电机 */
    device->motion_step_relevancy = step;
    /* 指定正常状态下的电平 */
    device->normal_level = level;

    /* 初始化断料检测引脚 */
    rt_pin_mode(device->pin, PIN_MODE_INPUT_PULLUP);

    /* 设置中断触发功能 */
    rt_uint32_t pin_irq_mode;
    /* 如果正常是高电平,则打开下降沿触发,反之则打开上升言触发 */
    pin_irq_mode = (level == PIN_HIGH) ?
                PIN_IRQ_MODE_FALLING : PIN_IRQ_MODE_RISING;
    rt_pin_attach_irq(device->pin, pin_irq_mode,
                      filament_runout_level_changed_event, (void *) device);
    rt_pin_irq_enable(device->pin, true);

    return true;
}

/*  获取断料检测传感器的检测状态 */
filament_runout_status_t filament_runout_status_get(filament_runout_t *device)
{
    ASSERT_NULL(device);

    return device->status;
}

/* 获取断料检测传感器的设备运转状态  */
filament_runout_err_t filament_runout_error_get(filament_runout_t *device)
{
    ASSERT_NULL(device);

    return device->err_status;
}

static filament_runout_ops_t s_filament_runout_ops = {
    .init = filament_runout_init,
    .status = filament_runout_status_get,
    .error = filament_runout_error_get,
};

/* 注册限位开关到系统表中,后便后续查看 */
bool filament_runout_register(filament_runout_t *device)
{
    ASSERT_NULL(device);

    MEM_MEMSET(device, 0, sizeof(filament_runout_t));
    device->ops = &s_filament_runout_ops;

    UNUSED(device);

    return true;
}
